package com.example.dw.util;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class FormulaExecutor {

    // 公式方法注册表
    private static   Map<String, Method> methodRegistry = new ConcurrentHashMap<>();
    // 方法实例注册表
    private static Map<String, Object> instanceRegistry = new ConcurrentHashMap<>();
    // 公式缓存
    private static   Map<String, List<FormulaPart>> formulaCache = new ConcurrentHashMap<>();

    // 公式解析正则表达式
    private static final Pattern FORMULA_PATTERN = Pattern.compile("@(\\w+)\\(([^)]*)\\)");
    private static final Pattern PARAM_SPLIT_PATTERN = Pattern.compile(",(?=(?:[^']*'[^']*')*[^']*$)");

    /**
     * 注册公式方法
     * @param methodName 方法名
     * @param instance 方法所属实例
     * @param method 方法对象
     */
    public void registerMethod(String methodName, Object instance, Method method) {
        methodRegistry.put(methodName.toLowerCase(), method);
        if(instance!=null){
            instanceRegistry.put(methodName.toLowerCase(), instance);
        }

    }

    /**
     * 注册对象的所有公共方法作为公式方法
     * @param instance 方法所属实例
     */
    public void registerObjectMethods(Object instance) {
        Class<?> clazz = instance.getClass();
        Method[] methods = clazz.getMethods();

        for (Method method : methods) {
            // 跳过Object类的方法
            if (method.getDeclaringClass() == Object.class) {
                continue;
            }
            registerMethod(method.getName(), instance, method);
        }
    }

    /**
     * 注册静态类的方法
     * @param clazz 静态类
     */
    public void registerStaticMethods(Class<?> clazz) {
        Method[] methods = clazz.getMethods();

        for (Method method : methods) {
            if (java.lang.reflect.Modifier.isStatic(method.getModifiers())) {
                registerMethod(method.getName(), null, method);
            }
        }
    }

    /**
     * 执行公式
     * @param formula 公式字符串，如："@add(@multiply(2,3),@subtract(5,1))"
     * @return 执行结果
     */
    public Object execute(String formula) {
        return execute(formula, new HashMap<>());
    }

    /**
     * 执行公式（带上下文参数）
     * @param formula 公式字符串
     * @param context 上下文参数
     * @return 执行结果
     */
    public Object execute(String formula, Map<String, Object> context) {
        try {
            List<FormulaPart> parts = parseFormula(formula);
            return evaluate(parts, context);
        } catch (Exception e) {
            throw new FormulaExecutionException("执行公式失败: " + formula, e);
        }
    }

    /**
     * 解析公式
     */
    private List<FormulaPart> parseFormula(String formula) {
        return formulaCache.computeIfAbsent(formula, this::doParseFormula);
    }

    /**
     * 实际解析公式逻辑
     */
    private List<FormulaPart> doParseFormula(String formula) {
        List<FormulaPart> parts = new ArrayList<>();
        int lastIndex = 0;
        Matcher matcher = FORMULA_PATTERN.matcher(formula);

        while (matcher.find()) {
            // 添加普通文本
            if (matcher.start() > lastIndex) {
                String text = formula.substring(lastIndex, matcher.start());
                parts.add(new TextPart(text));
            }

            // 添加公式部分
            String methodName = matcher.group(1);
            String paramsStr = matcher.group(2);
            parts.add(new MethodPart(methodName, paramsStr));

            lastIndex = matcher.end();
        }

        // 添加剩余文本
        if (lastIndex < formula.length()) {
            String text = formula.substring(lastIndex);
            parts.add(new TextPart(text));
        }

        return parts;
    }

    /**
     * 评估公式各部分
     */
    private Object evaluate(List<FormulaPart> parts, Map<String, Object> context) {
        if (parts.size() == 1) {
            return parts.get(0).evaluate(context, this);
        }

        // 拼接所有部分的结果
        StringBuilder result = new StringBuilder();
        for (FormulaPart part : parts) {
            Object partResult = part.evaluate(context, this);
            result.append(partResult != null ? partResult.toString() : "");
        }
        return result.toString();
    }

    /**
     * 执行方法调用
     */
    private Object invokeMethod(String methodName, Object[] parameters) {
        String key = methodName.toLowerCase();
        Method method = methodRegistry.get(key);
        Object instance = instanceRegistry.get(key);

        if (method == null) {
            throw new FormulaExecutionException("未找到公式方法: " + methodName);
        }

        try {
            // 转换参数类型以匹配方法签名
            Object[] convertedParams = convertParameters(method, parameters);
            return method.invoke(instance, convertedParams);
        } catch (Exception e) {
            throw new FormulaExecutionException("执行方法失败: " + methodName, e);
        }
    }

    /**
     * 转换参数类型
     */
    private Object[] convertParameters(Method method, Object[] parameters) {
        Class<?>[] paramTypes = method.getParameterTypes();
        Object[] converted = new Object[paramTypes.length];

        for (int i = 0; i < paramTypes.length; i++) {
            if (i < parameters.length) {
                converted[i] = convertType(parameters[i], paramTypes[i]);
            } else {
                converted[i] = getDefaultValue(paramTypes[i]);
            }
        }

        return converted;
    }

    /**
     * 类型转换
     */
    private Object convertType(Object value, Class<?> targetType) {
        if (value == null) {
            return getDefaultValue(targetType);
        }

        if (targetType.isInstance(value)) {
            return value;
        }

        String strValue = value.toString();

        if (targetType == String.class) {
            return strValue;
        } else if (targetType == Integer.class || targetType == int.class) {
            return Integer.parseInt(strValue);
        } else if (targetType == Long.class || targetType == long.class) {
            return Long.parseLong(strValue);
        } else if (targetType == Double.class || targetType == double.class) {
            return Double.parseDouble(strValue);
        } else if (targetType == Boolean.class || targetType == boolean.class) {
            return Boolean.parseBoolean(strValue);
        }else if(targetType == Number.class ) {
            return Integer.parseInt(strValue);
        } else {
            throw new FormulaExecutionException("不支持的参数类型: " + targetType);
        }
    }

    /**
     * 获取默认值
     */
    private Object getDefaultValue(Class<?> type) {
        if (type == int.class) return 0;
        if (type == long.class) return 0L;
        if (type == double.class) return 0.0;
        if (type == boolean.class) return false;
        return null;
    }

    /**
     * 解析参数字符串
     */
    private Object[] parseParameters(String paramsStr, Map<String, Object> context) {
        if (paramsStr == null || paramsStr.trim().isEmpty()) {
            return new Object[0];
        }

        String[] paramStrs = PARAM_SPLIT_PATTERN.split(paramsStr);
        Object[] parameters = new Object[paramStrs.length];

        for (int i = 0; i < paramStrs.length; i++) {
            String param = paramStrs[i].trim();
            parameters[i] = parseParameter(param, context);
        }

        return parameters;
    }

    /**
     * 解析单个参数
     */
    private Object parseParameter(String param, Map<String, Object> context) {
        // 如果是字符串（用单引号或双引号包围）
        if ((param.startsWith("'") && param.endsWith("'")) ||
                (param.startsWith("\"") && param.endsWith("\""))) {
            return param.substring(1, param.length() - 1);
        }

        // 如果是公式方法
        if (param.contains("@")) {
            return execute(param, context);
        }

        // 如果是上下文变量
        if (context.containsKey(param)) {
            return context.get(param);
        }

        // 尝试解析为数字
        try {
            if (param.contains(".")) {
                return Double.parseDouble(param);
            } else {
                return Long.parseLong(param);
            }
        } catch (NumberFormatException e) {
            // 如果不是数字，返回字符串
            return param;
        }
    }

    /**
     * 公式部分接口
     */
    private interface FormulaPart {
        Object evaluate(Map<String, Object> context, FormulaExecutor executor);
    }

    /**
     * 文本部分
     */
    private static class TextPart implements FormulaPart {
        private final String text;

        TextPart(String text) {
            this.text = text;
        }

        @Override
        public Object evaluate(Map<String, Object> context, FormulaExecutor executor) {
            return text;
        }
    }

    /**
     * 方法部分
     */
    private static class MethodPart implements FormulaPart {
        private final String methodName;
        private final String paramsStr;

        MethodPart(String methodName, String paramsStr) {
            this.methodName = methodName;
            this.paramsStr = paramsStr;
        }

        @Override
        public Object evaluate(Map<String, Object> context, FormulaExecutor executor) {
            Object[] parameters = executor.parseParameters(paramsStr, context);
            return executor.invokeMethod(methodName, parameters);
        }
    }

    /**
     * 公式执行异常
     */
    public static class FormulaExecutionException extends RuntimeException {
        public FormulaExecutionException(String message) {
            super(message);
        }

        public FormulaExecutionException(String message, Throwable cause) {
            super(message, cause);
        }
    }
}
